package com.lam.framework.aop;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.lam.common.base.domain.BaseEntity;
import com.lam.common.context.TokenUtils;
import com.lam.common.utils.DateUtil;
import com.lam.framework.annotation.ParamInject;
import com.lam.framework.operLog.annotation.Log;
import com.lam.framework.operLog.enums.BusinessType;

/**
 * 参数自动注入处理
 * 
 * @author lam
 */
@Order(2)
@Aspect
@Component
public class ParamAspect {
	
	private static final Logger logger = LoggerFactory.getLogger(ParamAspect.class);

	// 配置织入点
	@Pointcut("(@within(com.lam.framework.annotation.ParamInject) &&@target(com.lam.framework.annotation.ParamInject)) ||@annotation(com.lam.framework.annotation.ParamInject)")
    public void pointCut(){}
    
    @Around("pointCut()")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    	//获取方法的参数
    	Object[] args = injectParam(joinPoint, joinPoint.getArgs());
		return joinPoint.proceed(args);
	}

	public Object[] injectParam(ProceedingJoinPoint joinPoint, Object[] args) {
		
		if(args == null || args.length == 0){
			return args;
		}
		try {
			
			ParamInject paramInject = null;
			MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
			Method method = methodSignature.getMethod();
			if (method != null) {
				paramInject = method.getAnnotation(ParamInject.class);
			}
			if(paramInject == null){
				paramInject = joinPoint.getTarget().getClass().getAnnotation(ParamInject.class);
			}
			if(!check(paramInject)){
				return args;
			}
			Log log = method.getAnnotation(Log.class);
			//logger.debug("注入当前操作人合时间！")
			for (Object param : args) {
				if(log != null){
					inject(param, paramInject.injectCreate() && log.businessType() == BusinessType.INSERT, 
							paramInject.injectUpdate() && log.businessType() == BusinessType.UPDATE);
				}else{
					inject(param, paramInject.injectCreate(), paramInject.injectUpdate());
				}
			}
		} catch (Exception e) {
			logger.error("注入参数信息时异常, ", e);
		}
		return args;
	}
	
	private static boolean check(ParamInject paramInject){
		if (paramInject == null || !paramInject.inject()) {
			return false;
		}
		return paramInject.injectCreate() || paramInject.injectUpdate();
	}
	
	private static void inject(Object param, boolean injectCreate, boolean injectUpdate){
		if(param instanceof BaseEntity){
			BaseEntity entity = (BaseEntity)param;
			if (injectCreate) {
				entity.setCreateBy(TokenUtils.getLoginUsername());	
				entity.setCreateTime(DateUtil.newDate());
			}
			if (injectUpdate) {
				entity.setUpdateBy(TokenUtils.getLoginUsername());
				entity.setUpdateTime(DateUtil.newDate());
			}
		}
	}

}
